#include <iostream>
#include <string>
using namespace std;

// demo 1: easy derived
struct base
{
public:
    base(string szNm) : basename(szNm) {}
    string name() { return basename; }
    virtual void print(ostream &os)
    {
        os << basename << endl;
    }

private:
    string basename;
};

class derived : public base
{
public:
    derived(string szNm, int iVal) : base(szNm), mem(iVal) {}
    void print(ostream &os)
    {
        base::print(os);
        os << "---" << mem;
    }

private:
    int mem;
};

// demo 2: derived from diff priority
class Base
{
public:
    Base() {}
    void pub_mem() {}

protected:
    int prot_mem;

private:
    char pri_mem;
};

class Pub_Derv : public Base
{
public:
    void memfcn(Base &b)
    {
        b = *this;
        cout << "Pub_Derv::memfcn" << endl;
    }
};

class Prot_Derv : protected Base
{
public:
    void memfcn(Base &b)
    {
        b = *this;
        cout << "Prot_Derv::memfcn" << endl;
    }
};

class Priv_Derv : private Base
{
public:
    void memfcn(Base &b)
    {
        b = *this;
        cout << "Priv_Derv::memfcn" << endl;
    }
};

class Derived_from_Pub : public Pub_Derv
{
public:
    void memfcn(Base &b)
    {
        b = *this;
        cout << "Derived_from_Pub::memfcn" << endl;
    }
};

class Derived_from_Prot : protected Prot_Derv
{
public:
    void memfcn(Base &b)
    {
        b = *this;
        cout << "Derived_from_Prot::memfcn" << endl;
    }
};

// class Derived_from_Priv : private Priv_Derv
// {
// public:
//     void memfcn(Base &b)  // 由于是私有继承，Base构造函数也变成了私有，没有下文了
//     {
//         b = *this;
//         cout << "Derived_from_Priv::memfcn" << endl;
//     }
// };

int main()
{
    // demo 1
    base b("base");
    b.print(cout);
    derived d("derived", 42);
    d.print(cout);
    cout << endl;
    cout << "---" << endl;

    // demo 2
    Pub_Derv d1;
    Prot_Derv d2;
    Priv_Derv d3;
    Derived_from_Pub dd1;
    Derived_from_Prot dd2;
    // Derived_from_Priv dd3;
    Base base;
    Base *p = &base;
    p = &d1;
    // p = &d2;
    // p = &d3;
    p = &dd1;
    // p = &dd2;
    // p = &dd3;

    d1.memfcn(base);
    d2.memfcn(base);
    d3.memfcn(base);
    dd1.memfcn(base);
    dd2.memfcn(base);
    // dd3.memfcn(base);
}